package com.atguigu.tingshu.search.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.aggregations.Buckets;
import co.elastic.clients.elasticsearch._types.aggregations.LongTermsBucket;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.CompletionSuggestOption;
import co.elastic.clients.elasticsearch.core.search.Hit;

import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.json.JsonData;
import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;

import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.service.AlbumInfoIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.search.service.SuggestIndexRepository;
import com.atguigu.tingshu.user.client.UserFeignClient;
import com.atguigu.tingshu.vo.album.AlbumStatVo;

import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;

import java.util.stream.Collectors;


/**
 * 搜索服务输入
 *
 * @author ym
 * @date 2025/06/27 22:48
 */
@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {
    /**
     * 索引相册
     */
    private static final String INDEX_ALBUM = "albuminfo";
    /**
     * 建议索引
     */
    private static final String SUGGEST_INDEX = "suggestinfo";

    /**
     * 专辑信息索引库
     */
    @Autowired
    private AlbumInfoIndexRepository albumInfoIndexRepository;

    /**
     *
     */
    @Autowired
    private AlbumFeignClient albumFeignClient;

    /**
     * 用户假客户端
     */
    @Autowired
    private UserFeignClient userFeignClient;

    /**
     * 线程池执行器
     */
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    /**
     * 弹性搜索客户端
     */
    @Autowired
    private ElasticsearchClient elasticSearchClient;
    /**
     * 建议索引库
     */
    @Autowired
    SuggestIndexRepository suggestIndexRepository;
    /**
     * redis模板
     */
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    /**
     * 客户编辑
     */
    @Autowired
    RedissonClient redissonClient;

    /**
     * 上层相册
     *
     * @param albumId 专辑ID
     */
    @Override
    public void upperAlbum(Long albumId) {
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        CompletableFuture<AlbumInfo> abin = CompletableFuture.supplyAsync(() -> {
            //根据专辑id查询专辑信息
            AlbumInfo albumInfo = albumFeignClient.getAlbumInfo(albumId).getData();
            Assert.notNull(albumInfo, "专辑不存在");
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            albumInfoIndex.setCreateTime(new Date());
            List<AlbumAttributeValue> valueVoList = albumInfo.getAlbumAttributeValueVoList();
            if (!valueVoList.isEmpty()) {
                List<AttributeValueIndex> collect = valueVoList.stream().map(albumAttributeValue -> {
                    AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                    attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                    attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                    return attributeValueIndex;
                }).collect(Collectors.toList());

                albumInfoIndex.setAttributeValueIndexList(collect);

            }
            return albumInfo;
        }, threadPoolExecutor);
        //设置主博名称
        CompletableFuture<Void> userCompletableFuture = abin.thenAcceptAsync((albumInfo) -> {
            UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(albumInfo.getUserId()).getData();
            Assert.notNull(userInfoVo, "用户查询异常", albumInfo.getUserId());
            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());

        }, threadPoolExecutor);
        CompletableFuture<Void> voidCompletableFuture1 = abin.thenAcceptAsync((albumInfo) -> {
//设置三级分类
            BaseCategoryView baseCategoryView = albumFeignClient.getCategoryView(albumInfo.getCategory3Id()).getData();
            Assert.notNull(baseCategoryView, "查询分类异常", albumInfo.getCategory3Id());
            albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
            albumInfoIndex.setCategory3Id(baseCategoryView.getCategory3Id());
        }, threadPoolExecutor);
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            //设置播放量
            int num1 = RandomUtil.randomInt(1000, 2000);
            int num2 = RandomUtil.randomInt(500, 1000);
            int num3 = RandomUtil.randomInt(200, 400);
            int num4 = RandomUtil.randomInt(100, 200);
            albumInfoIndex.setPlayStatNum(num1);
            albumInfoIndex.setSubscribeStatNum(num2);
            albumInfoIndex.setBuyStatNum(num3);
            albumInfoIndex.setCommentStatNum(num4);
            //5.2 基于统计值计算出专辑得分 为不同统计类型设置不同权重
            BigDecimal bigDecimal1 = new BigDecimal(num4).multiply(new BigDecimal("0.4"));
            BigDecimal bigDecimal2 = new BigDecimal(num3).multiply(new BigDecimal("0.3"));
            BigDecimal bigDecimal3 = new BigDecimal(num2).multiply(new BigDecimal("0.2"));
            BigDecimal bigDecimal4 = new BigDecimal(num1).multiply(new BigDecimal("0.1"));
            BigDecimal hotScore = bigDecimal1.add(bigDecimal2).add(bigDecimal3).add(bigDecimal4);
            albumInfoIndex.setHotScore(hotScore.doubleValue());
        }, threadPoolExecutor);
        CompletableFuture.allOf(abin, userCompletableFuture, voidCompletableFuture1, voidCompletableFuture).join();
        //6.将索引库文档对象存入索引库
        albumInfoIndexRepository.save(albumInfoIndex);
        this.saveSuggestIndex(albumInfoIndex);
       /* AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        //根据专辑id查询专辑信息
        AlbumInfo albumInfo = albumFeignClient.getAlbumInfo(albumId).getData();
        Assert.notNull(albumInfo,"专辑不存在");
        BeanUtils.copyProperties(albumInfo, albumInfoIndex);
        albumInfoIndex.setCreateTime(new Date());
        List<AlbumAttributeValue> valueVoList = albumInfo.getAlbumAttributeValueVoList();
        if (!valueVoList.isEmpty()) {
            List<AttributeValueIndex> collect = valueVoList.stream().map(albumAttributeValue -> {
                AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                return attributeValueIndex;
            }).collect(Collectors.toList());

            albumInfoIndex.setAttributeValueIndexList(collect);

        }
        //设置主博名称
        UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(albumInfo.getUserId()).getData();
        Assert.notNull(userInfoVo, "用户查询异常", albumInfo.getUserId());
        albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
        //设置三级分类
        BaseCategoryView baseCategoryView = albumFeignClient.getCategoryView(albumInfoIndex.getCategory3Id()).getData();
        Assert.notNull(baseCategoryView, "查询分类异常", baseCategoryView.getCategory3Id());
        albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
        albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
        albumInfoIndex.setCategory3Id(baseCategoryView.getCategory3Id());
        //设置播放量
        int num1 = RandomUtil.randomInt(1000, 2000);
        int num2 = RandomUtil.randomInt(500, 1000);
        int num3 = RandomUtil.randomInt(200, 400);
        int num4 = RandomUtil.randomInt(100, 200);
        albumInfoIndex.setPlayStatNum(num1);
        albumInfoIndex.setSubscribeStatNum(num2);
        albumInfoIndex.setBuyStatNum(num3);
        albumInfoIndex.setCommentStatNum(num4);

        //5.2 基于统计值计算出专辑得分 为不同统计类型设置不同权重
        BigDecimal bigDecimal1 = new BigDecimal(num4).multiply(new BigDecimal("0.4"));
        BigDecimal bigDecimal2 = new BigDecimal(num3).multiply(new BigDecimal("0.3"));
        BigDecimal bigDecimal3 = new BigDecimal(num2).multiply(new BigDecimal("0.2"));
        BigDecimal bigDecimal4 = new BigDecimal(num1).multiply(new BigDecimal("0.1"));
        BigDecimal hotScore = bigDecimal1.add(bigDecimal2).add(bigDecimal3).add(bigDecimal4);
        albumInfoIndex.setHotScore(hotScore.doubleValue());
        //6.将索引库文档对象存入索引库
        albumInfoIndexRepository.save(albumInfoIndex);*/
        //加入到布隆过滤器
        redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER).add(albumId);
    }

    /**
     * 下架专辑
     *
     * @param albumId 相册id
     */
    @Override
    public void lowerAlbum(Long albumId) {
        albumInfoIndexRepository.deleteById(albumId);

    }

    /**
     * 相册信息
     *
     * @param albumIndexQuery 相册索引查询
     * @return {@link AlbumSearchResponseVo }
     */
    @SneakyThrows
    @Override
    public AlbumSearchResponseVo albumInfo(AlbumIndexQuery albumIndexQuery) {
        //1.创建查询对象
        SearchRequest searchRequest = this.buildSearchRequest(albumIndexQuery);

        SearchResponse<AlbumInfoIndex> search = elasticSearchClient.search(searchRequest, AlbumInfoIndex.class);
        AlbumSearchResponseVo albumSearchResponseVo = this.parseSearchResult(search, albumIndexQuery);
        return albumSearchResponseVo;
    }

    /**
     * 生成搜索请求
     *
     * @param albumIndexQuery 相册索引查询
     * @return {@link SearchRequest }
     */
    @Override
    public SearchRequest buildSearchRequest(AlbumIndexQuery albumIndexQuery) {
        SearchRequest.Builder builder = new SearchRequest.Builder();
        builder.index(INDEX_ALBUM);//索引
        //创建多条件对象
        BoolQuery.Builder allboolQuery = new BoolQuery.Builder();
        String keyword = albumIndexQuery.getKeyword();//封装关键字查询
        if (StringUtils.isNotBlank(keyword)) {
            BoolQuery.Builder keywordBuild = new BoolQuery.Builder();//创建关键字BOOL查询
//
            keywordBuild.should(s -> s.match(
                    m -> m.field("albumTitle")
                            .query(keyword))
            );//设置标题匹配查询
            keywordBuild.should(s -> s.match(
                    m -> m.field("albumInfo")
                            .query(keyword)));//设置描述匹配查询
            keywordBuild.should(s -> s.term(
                    m -> m.field("albumName")
                            .value(keyword)));//设置作者匹配查询
            allboolQuery.must(keywordBuild.build()._toQuery());//设置查询条件到最外层的bool对象
//封装三级分类
            if (albumIndexQuery.getCategory1Id() != null) {
                allboolQuery.filter(s -> s.term(
                        m -> m.field("category1Id")
                                .value(albumIndexQuery.getCategory1Id()))
                );
            }
            if (albumIndexQuery.getCategory2Id() != null) {
                allboolQuery.filter(s -> s.term(
                        m -> m.field("category2Id")
                                .value(albumIndexQuery.getCategory2Id()))
                );
            }
            if (albumIndexQuery.getCategory3Id() != null) {
                allboolQuery.filter(s -> s.term(
                        m -> m.field("category3Id")
                                .value(albumIndexQuery.getCategory3Id()))
                );
            }
            if (albumIndexQuery.getAttributeList() != null) {
                albumIndexQuery.getAttributeList().forEach(
                        attributeValue -> {
                            String[] split = attributeValue.split(":");
                            String attrbuteId = split[0];
                            String valueId = split[1];
                            if (split.length == 2 && split != null) {
                                allboolQuery.filter(t -> t.nested(n ->
                                        n.path("attributeValueIndexList")
                                                .query(q -> q.bool(b -> b.
                                                        filter(f -> f.term(t1 -> t1.field("attributeValueIndexList.attributeId").value(attrbuteId))).
                                                        filter(f1 -> f1.term(t2 -> t2.field("attributeValueIndexList.valueId").value(valueId)))

                                                ))));

                            }

                        });


            }
            builder.query(allboolQuery.build()._toQuery());// 构建查询条件
            // 分页
            builder.from((albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize());
            builder.size(albumIndexQuery.getPageSize());
            //高亮
            if (StringUtils.isNotBlank(keyword)) {
                builder.highlight(h -> h.fields("albumTitle",
                        hf -> hf.preTags("<span style='color:red'>").postTags("</span>")));
            }
            //排序
            String order = albumIndexQuery.getOrder();
            if (StringUtils.isNotBlank(order)) {
                String[] split = order.split(":");
                String filedNum = split[0];
                String orderType = split[1];
                if (split.length == 2 && split != null) {
                    String filed = "";
                    switch (filedNum) {
                        case "1" -> {
                            filed = "hotScore";
                        }
                        case "2" -> {
                            filed = "playStatNum";
                        }
                        case "3" -> {
                            filed = "createTime";
                        }

                    }
                    String finalFiled = filed;
                    builder.sort(s -> s.field(f -> f.field(finalFiled).
                            order("asc".equals(orderType) ? SortOrder.Asc : SortOrder.Desc)));


                }
                builder.source(s -> s.filter(so -> so.excludes(
                        "category1Id", "category2Id", "category3Id",
                        "attributeValueIndexList.attributeId", "attributeValueIndexList.valueId")));
            }

        }


        return builder.build();


    }

    /**
     * 解析搜索结果
     *
     * @param search          搜索
     * @param albumIndexQuery 相册索引查询
     * @return {@link AlbumSearchResponseVo }
     */
    @Override
    public AlbumSearchResponseVo parseSearchResult(SearchResponse<AlbumInfoIndex> search, AlbumIndexQuery albumIndexQuery) {
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        albumSearchResponseVo.setPageNo(albumIndexQuery.getPageNo());
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        //获取总条数
        long total = search.hits().total().value();
        albumSearchResponseVo.setTotal(total);
        //获取总页数
        long totalPage = total % albumIndexQuery.getPageSize() == 0 ? total / albumIndexQuery.getPageSize() : (total / albumIndexQuery.getPageSize()) + 1;
        albumSearchResponseVo.setTotalPages(totalPage);
        //获取查询的结果数据
        List<Hit<AlbumInfoIndex>> hits = search.hits().hits();
        if (hits != null && hits.size() > 0) {
            List<AlbumInfoIndexVo> collect = hits.stream().map(hit -> {
                AlbumInfoIndex source = hit.source();
                AlbumInfoIndexVo albumInfoIndexVo = BeanUtil.copyProperties(source, AlbumInfoIndexVo.class);
                //设置高亮
                if (StringUtils.isNotBlank(albumIndexQuery.getKeyword())) {
                    List<String> albumTitle = hit.highlight().get("albumTitle");
                    if (albumTitle != null && albumTitle.size() > 0) {
                        albumInfoIndexVo.setAlbumTitle(albumTitle.get(0));
                    }
                }


                return albumInfoIndexVo;

            }).collect(Collectors.toList());
            albumSearchResponseVo.setList(collect);
        }


        return albumSearchResponseVo;
    }

    /**
     * 获取顶级category3热门专辑列表
     *
     * @param category1Id category1 id
     * @return {@link List }<{@link Map }<{@link String }, {@link Object }>>
     */
    @SneakyThrows
    @Override
    public List<Map<String, Object>> getTopCategory3HotAlbumList(Long category1Id) {

        //根据一级分类id查询三级分类id
        List<Map<String, Object>> collect2 = new ArrayList<>();
        List<BaseCategory3> data = albumFeignClient.findTopBaseCategory3(category1Id).getData();


        //将三级分类id转换成以id为键的mapab'集合
        Map<Long, BaseCategory3> baseCategory3map = data.stream()
                .collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));
        Assert.notNull(data, "一级分类{}未包含三级分类", category1Id);
        List<Long> collect = data.stream().map(category3 -> {
            return category3.getId();
        }).collect(Collectors.toList());
        List<FieldValue> collect1 = collect.stream().map(category3Id -> {
            FieldValue fieldValue = FieldValue.of(category3Id);
            return fieldValue;
        }).collect(Collectors.toList());
        // //发送请求构建请求对象
        SearchResponse<AlbumInfoIndex> response = elasticSearchClient.search(s ->
                        s.index(INDEX_ALBUM)
                                .query(q -> q.terms(t -> t.field("category3Id")
                                        .terms(te -> te.value(collect1))))
                                .size(0)
                                .aggregations("category3Agg", a -> a.terms(t -> t.field("category3Id").size(10))
                                        .aggregations("top6Agg", a1 -> a1.topHits(th -> th.size(6).sort(sort -> sort.field(s1 -> s1.field("playStatNum")
                                                .order(SortOrder.Desc))))))
                , AlbumInfoIndex.class);

        Aggregate category3Agg = response.aggregations().get("category3Agg");
        Buckets<LongTermsBucket> buckets = category3Agg.lterms().buckets();
        List<LongTermsBucket> array = buckets.array();
        if (CollectionUtil.isNotEmpty(array)) {
            //遍历集合处理各个分组
            collect2 = array.stream().map(a -> {
                Map<String, Object> stringObjectHashMap = new HashMap<>();
                long key = a.key();
                BaseCategory3 baseCategory3 = baseCategory3map.get(key);
                stringObjectHashMap.put("baseCategory3", baseCategory3);
                Aggregate top6Agg = a.aggregations().get("top6Agg");
                //获取数据
                List<Hit<JsonData>> hits = top6Agg.topHits().hits().hits();
                if (CollectionUtil.isNotEmpty(hits)) {
                    List<AlbumInfoIndex> collect3 = hits.stream().map(hit -> {
                        JsonData source = hit.source();
                        AlbumInfoIndex albumInfoIndex = JSON.parseObject(source.toString(), AlbumInfoIndex.class);
                        return albumInfoIndex;
                    }).collect(Collectors.toList());
                    stringObjectHashMap.put("list", collect3);
                }

                return stringObjectHashMap;
            }).collect(Collectors.toList());
        }
        return collect2;
    }

    /**
     * 保存建议索引
     *
     * @param albumInfoIndex 相册信息索引
     */
    @Override
    public void saveSuggestIndex(AlbumInfoIndex albumInfoIndex) {
        //建立提词库
        SuggestIndex suggestIndex = new SuggestIndex();
        suggestIndex.setId(albumInfoIndex.getId().toString());
        suggestIndex.setTitle(albumInfoIndex.getAlbumTitle());
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
//设置提词对象 汉字提词或单词
        //设置提词对象 拼音提词
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinyinUtil.getPinyin(albumInfoIndex.getAlbumTitle(), "")}));
        //设置提词对象 拼音首字母提词
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinyinUtil.getFirstLetter(albumInfoIndex.getAlbumTitle(), "")}));
        suggestIndexRepository.save(suggestIndex);//添加到提词库


    }

    /**
     * 自动补全
     *
     * @param keyword 关键词
     * @return {@link List }<{@link String }>
     */

    @Override
    public List<String> completeSuggest(String keyword) {
//1.查询提词库
        try {


            SearchResponse<SuggestIndex> response = elasticSearchClient.search(
                    s -> s.index(SUGGEST_INDEX)
                            .suggest(s1 -> s1.suggesters("mySuggestKeyword", fs -> fs.prefix(keyword).completion(c -> c.field("keyword").size(10).skipDuplicates(true)))
                                    .suggesters("mySuggestPinyin", fs -> fs.prefix(keyword).completion(c -> c.field("keywordPinyin").size(10).skipDuplicates(true)))
                                    .suggesters("mySuggestSequence", fs -> fs.prefix(keyword).completion(c -> c.field("keywordSequence").size(10).skipDuplicates(true)))
                            )
                    , SuggestIndex.class
            );
            //构建查询提词库DSL,获取查询结果
            //3.封装结果去重
            HashSet<String> set = new LinkedHashSet<>();
            set.addAll(this.parseSuggestList(response, "mySuggestKeyword"));
            set.addAll(this.parseSuggestList(response, "mySuggestPinyin"));
            set.addAll(this.parseSuggestList(response, "mySuggestSequence"));
            System.out.println(set);
            // 方法一：使用 ArrayList 构造函数
            List<String> resultList = new ArrayList<>(set);
            if (set.size() > 10) {
                resultList = resultList.subList(0, 10);
                //4.返回结果
                return resultList;

            }
            //查询专辑索引库
            SearchResponse<AlbumInfoIndex> albumInfoIndexSearchResponse = elasticSearchClient.search(s -> s.index(INDEX_ALBUM).
                    query(q -> q.match(t -> t.field("albumTitle").query(keyword))), AlbumInfoIndex.class);
//解析结果
            List<Hit<AlbumInfoIndex>> hits = albumInfoIndexSearchResponse.hits().hits();
            if (CollectionUtil.isNotEmpty(hits)) {
                for (Hit<AlbumInfoIndex> hit : hits) {
                    AlbumInfoIndex source = hit.source();
                    set.add(source.getAlbumTitle());
                    if (set.size() > 10) {
                        break;
                    }
                }
            }
            return new ArrayList<>(set);
        } catch (Exception e) {
            log.error("[搜索服务]建议自动补全出现错误{}", e);
            throw new RuntimeException(e);
        }
    }


    /**
     * 解析建议列表
     *
     * @param response         响应
     * @param mySuggestKeyword 我的建议关键字
     * @return {@link Collection<String>}
     */
    @Override
    public Collection<String> parseSuggestList(SearchResponse<SuggestIndex> response, String mySuggestKeyword) {
        //获取提词组数据
        List<Suggestion<SuggestIndex>> suggestions = response.suggest().get(mySuggestKeyword);
        //创建接收结果
        List<String> list = new ArrayList<>();
        for (Suggestion<SuggestIndex> suggestion : suggestions) {
            List<CompletionSuggestOption<SuggestIndex>> options = suggestion.completion().options();
            if (CollectionUtil.isNotEmpty(options)) {
                for (CompletionSuggestOption<SuggestIndex> option : options) {
                    SuggestIndex source = option.source();

                    list.add(source.getTitle());
                }
            }

        }
        return list;
    }

    /**
     * 获取综合数据
     *
     * @param albumId 相册id
     * @return 映射<字符串 ， 对象>
     */

    @Override
    public Map<String, Object> getAlbumInfo(Long albumId) {
        //布隆过滤器中获得
        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConstant.ALBUM_BLOOM_FILTER);
        boolean contains = bloomFilter.contains(albumId);
        if (!contains) {
            throw new GuiguException(404, "访问专辑不存在");
        }
        ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
                    AlbumInfo data = albumFeignClient.getAlbumInfo(albumId).getData();
                    Assert.notNull(data, "查询专辑出现异常");
                    map.put("albumInfo", data);
                    return data;
                }

                , threadPoolExecutor);
        CompletableFuture<Void> voidCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {

            BaseCategoryView data = albumFeignClient.getCategoryView(albumInfo.getCategory3Id()).getData();
            Assert.notNull(data, "查询分类出现异常");
            map.put("baseCategoryView", data);
        }, threadPoolExecutor);
        CompletableFuture<Void> voidCompletableFuture1 = CompletableFuture.runAsync(() -> {
            AlbumStatVo data = albumFeignClient.getAlbumStatVo(albumId).getData();
            Assert.notNull(data, "查询统计出现异常");
            map.put("albumStatVo", data);
        }, threadPoolExecutor);
        CompletableFuture<Void> voidCompletableFuture2 = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            UserInfoVo data = userFeignClient.getUserInfoVo(albumInfo.getUserId()).getData();
            Assert.notNull(data, "查询用户信息出现错误", albumInfo.getUserId());
            map.put("announcer", data);
        }, threadPoolExecutor);
        CompletableFuture.allOf(albumInfoCompletableFuture, voidCompletableFuture, voidCompletableFuture1, voidCompletableFuture2).join();
        return map;
    }

    /**
     * 更新最新专辑排名
     *
     * @author ym
     * @date 2025/06/25 17:41
     */
    @Override
    public void updateLatelyAlbumRanking() {
        List<BaseCategory1> category1List = albumFeignClient.getAllCategory1().getData();
        Assert.notEmpty(category1List, "查询一级分类出现异常");
        //2.循环遍历1级分类列表，获取该分类下5种不同排序方式榜单专辑
        try {
            for (BaseCategory1 baseCategory1 : category1List) {
                String[] rankingDimensionArray =
                        new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
                //3.循环遍历排序方式
                for (String rankingDimension : rankingDimensionArray) {
                    SearchResponse<AlbumInfoIndex> searchResponse = elasticSearchClient.search(s -> s.index(INDEX_ALBUM).
                            query(q -> q.term(t -> t.field("category1Id").value(baseCategory1.getId())))
                            .sort(sort -> sort.field(s1 -> s1.field(rankingDimension).order(SortOrder.Desc)))
                            .size(10), AlbumInfoIndex.class);
                    List<Hit<AlbumInfoIndex>> hits = searchResponse.hits().hits();
                    //得到榜单专辑列表
                    List<AlbumInfoIndex> albumInfoIndexList = hits.stream().map(hit -> hit.source()).toList();
                    //将榜单专辑列表存入redis
                    Long id = baseCategory1.getId();
                    String s = RedisConstant.RANKING_KEY_PREFIX + id;

                    redisTemplate.opsForHash().put(s, rankingDimension, albumInfoIndexList);

                }

            }


        } catch (IOException e) {
            log.error("[搜索服务]更新最新专辑排名出现错误{}", e);
            throw new RuntimeException(e);
        }

    }

    /**
     * 查找排行榜
     *
     * @param category1Id 分类
     * @param dimension   尺寸
     * @return {@link List<AlbumInfoIndex>}
     */
    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String dimension) {
        String s = RedisConstant.RANKING_KEY_PREFIX + category1Id;
        Boolean flag = redisTemplate.opsForHash().hasKey(s, dimension);
        if (flag) {
            List<AlbumInfoIndex> albumInfoIndexList = (List<AlbumInfoIndex>) redisTemplate.opsForHash().get(s, dimension);
            return albumInfoIndexList;
        }
        return null;
    }
}


